#include "bsp_can.h"
#include "n32g430_gpio.h"
#include "n32g430_can.h"
#include "n32g430_rcc.h"
#include "log.h"
#include <string.h>

// 全局变量
static CAN_RxCallback g_rx_callback = NULL;
static CanRxMessage RxMessage;

// 消息缓冲区
static struct {
    CAN_Message messages[CAN_RX_BUFFER_SIZE];
    volatile uint8_t write_index;
    volatile uint8_t read_index;
} can_rx_buffer = {0};

/**
 * @brief  从缓冲区获取消息
 * @param  msg: 消息结构体指针
 * @return 1: 成功, 0: 失败(缓冲区空)
 */
uint8_t BSP_CAN_GetMessage(CAN_Message* msg)
{
    // 检查缓冲区是否为空
    if (can_rx_buffer.read_index == can_rx_buffer.write_index) {
        return 0;  // 缓冲区空
    }
    
    // 从缓冲区读取消息
    memcpy(msg, &can_rx_buffer.messages[can_rx_buffer.read_index], sizeof(CAN_Message));
    can_rx_buffer.read_index = (can_rx_buffer.read_index + 1) % CAN_RX_BUFFER_SIZE;
    
    return 1;
}

/**
 * @brief  初始化CAN通信
 */
void BSP_CAN_Init(void)
{
    GPIO_InitType GPIO_InitStructure;
    CAN_InitType CAN_InitStructure;
    CAN_FilterInitType CAN_FilterInitStructure;

    /* 使能时钟 */
    RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
    RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_CAN);
    RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);

    /* 配置CAN引脚 */
    GPIO_InitStructure.Pin = CAN_RX_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = CAN_RX_GPIO_AF;
    GPIO_Peripheral_Initialize(CAN_RX_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = CAN_TX_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = CAN_TX_GPIO_AF;
    GPIO_Peripheral_Initialize(CAN_TX_GPIO_PORT, &GPIO_InitStructure);

    /* CAN单元初始化 */
    CAN_InitStructure.TTCM = DISABLE;
    CAN_InitStructure.ABOM = ENABLE;    // 启用自动离线管理
    CAN_InitStructure.AWKUM = DISABLE;
    CAN_InitStructure.NART = DISABLE;   // 启用自动重传
    CAN_InitStructure.RFLM = DISABLE;
    CAN_InitStructure.TXFP = ENABLE;
    CAN_InitStructure.OperatingMode = CAN_NORMAL_MODE;
    CAN_InitStructure.RSJW = CAN_RSJW_1TQ;
    CAN_InitStructure.TBS1 = CAN_TBS1_8TQ;
    CAN_InitStructure.TBS2 = CAN_TBS2_7TQ;
    CAN_InitStructure.BaudRatePrescaler = 2;  // 1Mbps
    CAN_Initializes(CAN, &CAN_InitStructure);

    /* CAN过滤器初始化 - 接收所有消息 */
    CAN_FilterInitStructure.Filter_Num = 0;  // 使用过滤器0
    CAN_FilterInitStructure.Filter_Mode = CAN_FILTER_IDMASKMODE;  // ID掩码模式
    CAN_FilterInitStructure.Filter_Scale = CAN_FILTER_32BITSCALE;  // 32位过滤器
    CAN_FilterInitStructure.Filter_HighId = 0x0000;  // 接收所有ID
    CAN_FilterInitStructure.Filter_LowId = 0x0000;
    CAN_FilterInitStructure.FilterMask_HighId = 0x0000;  // 不使用掩码
    CAN_FilterInitStructure.FilterMask_LowId = 0x0000;
    CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FILTER_FIFO0;
    CAN_FilterInitStructure.Filter_Act = ENABLE;
    CAN_Filter_Initializes(&CAN_FilterInitStructure);

    /* 使能CAN接收中断 */
    CAN_Config_Interrupt_Enable(CAN, CAN_INT_FMP0);

    /* 配置NVIC */
    NVIC_InitType NVIC_InitStructure;
    NVIC_Priority_Group_Set(NVIC_PER2_SUB2_PRIORITYGROUP);
    NVIC_InitStructure.NVIC_IRQChannel = CAN_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;  // 提高中断优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Initializes(&NVIC_InitStructure);

    LOGI("CAN Initialized, Filter configured to accept all messages\r\n");
}

/**
 * @brief  CAN发送数据
 */
uint8_t BSP_CAN_Transmit(uint32_t id, uint8_t *data, uint8_t len)
{
    uint8_t mbox;
    uint16_t timeout = 0;
    CanTxMessage TxMessage;

    /* 配置发送消息 */
    if (id > 0x7FF) {
        TxMessage.IDE = CAN_EXTENDED_ID;
        TxMessage.ExtId = id;
    } else {
        TxMessage.IDE = CAN_STANDARD_ID;
        TxMessage.StdId = id;
    }
    TxMessage.RTR = CAN_RTRQ_DATA;
    TxMessage.DLC = len;
    
    for (uint8_t i = 0; i < len; i++) {
        TxMessage.Data[i] = data[i];
    }

    /* 发送消息 */
    mbox = CAN_Transmit_Message_initializes(CAN, &TxMessage);
    
    /* 等待发送完成 */
    while ((CAN_Transmit_Status_Get(CAN, mbox) != CAN_TXSTS_OK) && (timeout < 0xFFFF)) {
        timeout++;
    }

    if (timeout >= 0xFFFF) {
        return 1;
    }
    return 0;
}

/**
 * @brief  注册CAN接收回调函数
 */
void BSP_CAN_RegisterCallback(CAN_RxCallback callback)
{
    g_rx_callback = callback;
}

/**
 * @brief  CAN接收中断服务函数
 */
void CAN_RX0_IRQHandler(void)
{
    /* 接收消息 */
    CAN_Message_Receive(CAN, CAN_FIFO0, &RxMessage);
    
    // 计算下一个写入位置
    uint8_t next_write = (can_rx_buffer.write_index + 1) % CAN_RX_BUFFER_SIZE;
    
    // 检查缓冲区是否已满
    if (next_write != can_rx_buffer.read_index) {
        // 将消息存入缓冲区
        CAN_Message* msg = &can_rx_buffer.messages[can_rx_buffer.write_index];
        msg->id = RxMessage.IDE == CAN_EXTENDED_ID ? RxMessage.ExtId : RxMessage.StdId;
        msg->len = RxMessage.DLC;
        memcpy(msg->data, RxMessage.Data, RxMessage.DLC);
        
        // 更新写指针
        can_rx_buffer.write_index = next_write;
    } else {
        LOGW("CAN接收缓冲区溢出!\r\n");
    }
}